// Copyright: 北京经海科技有限公司
// Author: Ivan (李渊)
// Date: 2015-03-01
// Last Modified On: 2015-05-22
// Description: 用于显示CCD采集的图像，并可以在上面增加各种标注

#include "DisplayWidget.h"
#include "element.h"
#include <QtGui>
#include <stdint.h>

DisplayWidget::DisplayWidget(ImageFormat format, QWidget *parent)
        : ImageView(format, parent),
          pShapeFind(NULL),
          pcurrentShape(NULL)
{
    setDrawType(Element::NONE);
    m_linePen.setWidth(DEFAULT_LINE_WIDTH);
    m_linePen.setColor(Qt::red);
    m_textFont = QFont("宋体", DEFAULT_FONT_SIZE, QFont::Bold);
    setMouseTracking( true );
    m_ExtLine = 0;
}

void DisplayWidget::setReferenceLine(int pos)
{
    m_ExtLine = pos;
    HTLine::setHLine(pos);
    VTLine::setVLine(pos);
    update();
}

void DisplayWidget::addCircle(QPoint center, double radius)
{
    if( pcurrentShape == NULL )
    {
        DrawRCircle *p = new DrawRCircle;
        p->setLinePen(m_linePen);
        p->setTextFont(m_textFont);
        p->build(center, radius);
        m_shapeList << p;
        update();
    }
}

void DisplayWidget::setColor(QColor color)
{
    if(color.isValid())
    {
        m_linePen.setColor(color);
    }
}

void DisplayWidget::setLineWidth(int width)
{
    m_linePen.setWidth(width);
}

void DisplayWidget::setTextSize(int width)
{
    m_textFont.setPointSize(width);
}

DisplayWidget::~DisplayWidget()
{
    clearAll();
}

void DisplayWidget::setDrawType(enum Element::DrawType type)
{
    if(pcurrentShape != NULL)
    {
        Element *p = m_shapeList.takeLast();
        if(p)
        {
            delete p;
        }
        pcurrentShape = NULL;
        update();
    }
    m_drawType = type;
}

void DisplayWidget::setScale(double scale)
{
    Element::setScale(scale);
    QList<Element *>::iterator iter;
    for (iter = m_shapeList.begin(); iter != m_shapeList.end(); ++iter)
    {
        (*iter)->updateText();
    }
    update();
}

Element* DisplayWidget::findShape(const QPoint &pt)
{
    Element *pShape = NULL;
    QList<Element *>::iterator iter;
    for (iter = m_shapeList.begin(); iter != m_shapeList.end(); ++iter)
    {
        if( (*iter)->isInTextBox(pt) )
        {
            pShape = *iter;
            break;
        }
    }
    return pShape;
}

void DisplayWidget::mouseLeftButtonPress(QPoint point)
{
    if( m_drawType == Element::NONE )
    {
        pShapeFind = findShape(point);
        return;
    }
    //qDebug() << "pcurrentShape = " << pcurrentShape;
    if( pcurrentShape != NULL && pcurrentShape->state() != Element::DS_FINISH )
    {
        pcurrentShape->mouseLButtonPress(point);
    }
    else
    {
        switch (m_drawType)
        {
        case Element::LINE:
            pcurrentShape = new DrawLine;
            break;
        case Element::PARALLEL:
            pcurrentShape = new DrawParallelLine;
            break;
        case Element::RCIRCLE:
            pcurrentShape = new DrawRCircle;
            break;
        case Element::LCIRCLE:
            pcurrentShape = new DrawLCircle;
            break;
        case Element::RECTAGLE:
            pcurrentShape = new DrawRect;
            break;
        case Element::CORNER:
            pcurrentShape = new DrawCorner;
            break;
        case Element::DOTSTOLINE:
            pcurrentShape = new DrawDots2Line;
            break;
        case Element::HTLINE:
            //pcurrentShape = new HTLine;
            break;
        case Element::VTLINE:
            //pcurrentShape = new VTLine;
            break;
        case Element::POLYLINE:
            pcurrentShape = new DrawPolyline;
            //qDebug() << "new DrawPolyline";
            break;
        case Element::POLYGON:
            pcurrentShape = new DrawPolygon;
            break;
        case Element::PCIRCLE:
            pcurrentShape = new DrawPCIRCLE;
            break;
        default:
            return;
        }
        pcurrentShape->setLinePen(m_linePen);
        pcurrentShape->setTextFont(m_textFont);
        pcurrentShape->mouseLButtonPress(point);
        m_shapeList << pcurrentShape;
    }
    update();
}

void DisplayWidget::mouseRightButtonPress(QPoint point)
{
    if( pcurrentShape != NULL && pcurrentShape->state() != Element::DS_FINISH )
    {
        pcurrentShape->mouseRButtonPress(point);
        if( pcurrentShape->state() == Element::DS_FINISH ) //表明当前图形已经完全确定
        {
            pcurrentShape = NULL;
        }
        update();
        return;
    }
}

void DisplayWidget::mousePressEvent( QMouseEvent * event )
{
    //qDebug() << "mousePressEvent";
    QPoint point = event->pos()/ m_zoom_factor;
    m_startPoint = point;
    if( event->button() == Qt::RightButton )
	{
        mouseRightButtonPress(point);
	}
    else if( event->button() == Qt::LeftButton )
    {
        mouseLeftButtonPress(point);
    }
    ImageView::mousePressEvent(event);
}

double DisplayWidget::getLength(bool &ok)
{
    double length = 0;
    if( !m_shapeList.isEmpty() )
    {
        Element *p = m_shapeList.last();
        //qDebug() << "p->type() " << p->type();
        if( p->type() == Element::LINE )
        {
            length = ((DrawLine *) p)->getLength();
            ok = true;
            return length;
        }
        else if( p->type() == Element::RCIRCLE )
        {
            length = ((DrawRCircle *) p)->getDiameter();
            ok = true;
            return length;
        }
        else if( p->type() == Element::LCIRCLE )
        {
            length = ((DrawLCircle *) p)->getDiameter();
            ok = true;
            return length;
        }
    }
    ok = false;
    return length;
}

bool DisplayWidget::getRectagel(QRect &rect)
{
    if( !m_shapeList.isEmpty() )
    {
        Element *p = m_shapeList.last();
        //qDebug() << "p->type() " << p->type();
        if( p->type() == Element::RECTAGLE )
        {
            ((DrawRect *) p)->getRect(rect);
            return true;
        }
    }
    return false;
}

void DisplayWidget::calibrate()
{

}

void DisplayWidget::undo(void)
{
    if( !m_shapeList.isEmpty() )
    {
        Element *p = m_shapeList.takeLast();
        pcurrentShape = NULL;
        delete p;
        update();
    }
}

void DisplayWidget::clearAll(void)
{
    while( !m_shapeList.isEmpty() )
    {
        Element *p = m_shapeList.takeLast();
		pcurrentShape = NULL;
        delete p;
    }
    update();
}

void DisplayWidget::mouseReleaseEvent( QMouseEvent * event )
{
    //qDebug() << "mouseReleaseEvent";
    pShapeFind = NULL;
    if( event->button() == Qt::RightButton )
    {
        //if()
        //undo();
        return;
    }
    if( m_drawType != Element::NONE  && pcurrentShape != NULL )
    {
        QPoint point = event->pos()/ m_zoom_factor;
        pcurrentShape->mouseLButtonRelease(point);
        //qDebug() << pcurrentShape->state();
        if( pcurrentShape->state() == Element::DS_ERROR )
        {
            Element *p = m_shapeList.takeLast();
            delete p;
            pcurrentShape = NULL;
        }
        else if( pcurrentShape->state() == Element::DS_FINISH ) //表明当前图形已经完全确定
        {
            pcurrentShape = NULL;
        }
    }

    update();
}

void DisplayWidget::mouseMoveEvent( QMouseEvent * event )
{
    QPoint point = event->pos() / m_zoom_factor;

    if( m_drawType == Element::NONE && pShapeFind != NULL )
    {
        QPoint offset = point - m_startPoint;
        pShapeFind->textMove(offset);
        m_startPoint = point;
        update();
        return;
    }
    if( pcurrentShape == NULL )
    {
        return;
    }
    pcurrentShape->mouseMove(point);
    update();

//    qDebug() << "mouseMoveEvent";
}

QImage DisplayWidget::getImage(bool withMark)
{
    m_image_mutex.lock();
    QImage image = m_image.copy();
    m_image_mutex.unlock();
    if( withMark )
    {
        QPainter painter(&image);
        painter.setRenderHint ( QPainter::Antialiasing, true );
        drawElement(painter);
        //drawCross(painter);
    }
    return image;
}

bool DisplayWidget::saveImage( const QString & fileName, bool checked )
{
	m_image_mutex.lock();
    QImage image = m_image.copy();
	m_image_mutex.unlock();
    if( checked )
    {
		QPainter painter(&image);
		painter.setRenderHint ( QPainter::Antialiasing, true );
        drawElement(painter);
    }
    return image.save(fileName);
}

void DisplayWidget::paintEvent( QPaintEvent * event )
{
    (void) event;
    ImageView::paintEvent(event);
    QPainter painter(this);
    painter.setRenderHint ( QPainter::Antialiasing, true );
    painter.save();
    painter.scale(m_zoom_factor, m_zoom_factor);
    drawElement(painter);
    painter.restore();
}

void DisplayWidget::drawElement(QPainter &painter)
{
    QListIterator<Element *> iter(m_shapeList);
    for(;iter.hasNext();)
    {
        Element * pShape = iter.next();
        pShape->draw(painter);
    }
}


